package service

import (
	"context"
	stdErrors "errors"
	"github.com/go-kratos/kratos/v2/log"
	v1 "kratos-realword/api/realworld/v1"
	"kratos-realword/internal/conf"
	"kratos-realword/internal/dao"
	"kratos-realword/internal/errors"
	"kratos-realword/internal/middleware/auth"
	"kratos-realword/internal/pojo"
	"kratos-realword/internal/util"
	"strings"
)

type UserService struct {
	userDao dao.UserDao
	jwtConf *conf.JWT
	log     *log.Helper
}

type UserRegister struct {
	Username string
	Email    string
	Password string
}

type UserLogin struct {
	Email    string
	Password string
}

func NewUserService(userDao dao.UserDao, jwtConf *conf.JWT, logger log.Logger) *UserService {
	return &UserService{userDao: userDao, jwtConf: jwtConf, log: log.NewHelper(logger)}
}

// generateToken 根据用户 userEmail 生成 Token
func (service *UserService) generateToken(userEmail string) string {
	return auth.GenerateToken(service.jwtConf, userEmail)
}

func (service *UserService) Login(ctx context.Context, userLogin *UserLogin) (*pojo.User, error) {
	if len(userLogin.Email) == 0 || strings.Trim(userLogin.Email, " ") == "" {
		return nil, errors.NewHTTPError(422, "email cannot be empty")
	}
	if len(userLogin.Password) == 0 || strings.Trim(userLogin.Password, " ") == "" {
		return nil, errors.NewHTTPError(422, "password cannot be empty")
	}
	//从数据库查询用户
	user, err := service.userDao.GetUserByEmail(ctx, userLogin.Email)
	if user == nil {
		//用户不存在
		return nil, stdErrors.New("user not exist")
	}
	if err != nil {
		return nil, err
	}
	//对比数据库查询出来的密码和明文进行比较
	err = util.VerifyPassword(user.PasswordHash, userLogin.Password)
	if err != nil {
		return nil, stdErrors.New("密码错误")
	}
	//生成 token
	user.Token = service.generateToken(user.Email)
	return user, nil
}

func (service *UserService) Register(ctx context.Context, userRegister *UserRegister) (*pojo.User, error) {
	if getUser, _ := service.userDao.GetUserByEmail(ctx, userRegister.Email); getUser != nil {
		//用户已存在
		return nil, stdErrors.New("用户已存在")
	}
	hashPwd, err := util.HashPassword(userRegister.Password)
	if err != nil {
		return nil, err
	}
	user := pojo.User{
		Username:     userRegister.Username,
		Email:        userRegister.Email,
		PasswordHash: hashPwd,
	}
	if err := service.userDao.CreateUser(ctx, &user); err != nil {
		return nil, err
	}
	user.Token = service.generateToken(user.Email)
	return &user, nil
}

func (service *UserService) GetCurrentUser(ctx context.Context) (*pojo.User, error) {
	user, err := service.userDao.GetUserByEmail(ctx, auth.FromContext(ctx).UserEmail)
	if err != nil {
		return nil, err
	}
	return user, nil
}

func (service *UserService) UpdateUser(ctx context.Context, req *v1.UpdateUserRequest) (*pojo.User, error) {
	return nil, nil
}
